import gpiod
import threading
import time
import logging
from datetime import timedelta
from gpiod.line import Bias, Edge

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('/var/log/app.log'),
        logging.StreamHandler()
    ]
)

class GPIOMonitor:
    def __init__(self, chip_name, button_pin, long_press_sec=3):
        self.chip_name = chip_name
        self.button_pin = button_pin
        self.long_press_sec = long_press_sec
        self._monitor_thread = None
        self._monitoring = False
        self._button_pressed = False
        self._press_time = 0
        self.on_long_press = None
        self.on_press = None  # 新增

    def set_callbacks(self, on_long_press=None, on_press=None):  # 新增on_press
        self.on_long_press = on_long_press
        self.on_press = on_press

    def start(self):
        self._monitoring = True
        self._monitor_thread = threading.Thread(target=self._monitor_task, daemon=True)
        self._monitor_thread.start()

    def stop(self):
        self._monitoring = False
        if self._monitor_thread and self._monitor_thread.is_alive():
            self._monitor_thread.join(timeout=2)

    def _monitor_task(self):
        """使用monitor.py的方式监控GPIO"""
        chip_path = f"/dev/{self.chip_name}"
        logging.info(f"开始监控GPIO: {chip_path}:{self.button_pin}")
        
        try:
            # 使用monitor.py的方式配置GPIO
            with gpiod.request_lines(
                chip_path,
                consumer="gpio_monitor",
                config={
                    self.button_pin: gpiod.LineSettings(
                        edge_detection=Edge.BOTH,
                        bias=Bias.PULL_UP,
                        debounce_period=timedelta(milliseconds=10),
                    )
                },
            ) as request:
                while self._monitoring:
                    try:
                        # 阻塞直到至少有一个事件可用
                        for event in request.read_edge_events():
                            if not self._monitoring:
                                break
                            
                            # 处理按键事件
                            self._handle_button_event(event)
                            
                    except Exception as e:
                        if self._monitoring:
                            logging.error(f"GPIO事件读取错误: {e}")
                            time.sleep(0.1)
                        else:
                            break
                            
        except Exception as e:
            logging.error(f"GPIO监控任务错误: {e}")

    def _handle_button_event(self, event):
        """处理按键事件"""
        try:
            # 判断事件类型
            if event.event_type == event.Type.RISING_EDGE:
                # 按键按下
                self._button_pressed = True
                self._press_time = time.time()
                logging.info("按键按下")
                
            elif event.event_type == event.Type.FALLING_EDGE:
                # 按键释放
                if self._button_pressed:
                    duration = time.time() - self._press_time
                    self._button_pressed = False
                    
                    if duration >= self.long_press_sec:
                        # 长按
                        logging.info(f"按键长按 ({duration:.1f}s) - 切换录制状态")
                        if self.on_long_press:
                            self.on_long_press()
                    else:
                        # 短按
                        logging.info(f"按键短按 ({duration:.1f}s)")
                        if self.on_press:
                            self.on_press()
        except Exception as e:
            logging.error(f"处理按键事件失败: {e}") 